import json
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
from datetime import datetime
import os

# 设置中文显示
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题


def load_data(file_path):
    """加载JSON数据并转换为DataFrame"""
    with open(file_path, 'r', encoding='utf-8') as f:
        data = json.load(f)

    df = pd.DataFrame(data)

    # 转换时间戳为datetime对象
    df['bizTime'] = pd.to_datetime(df['bizTime'], unit='ms')

    # 将金额从分转换为元
    df['amount'] = df['amount'] / 100

    # 将recType转换为收支类型
    df['type'] = df['recType'].map({1: '支出', 2: '收入'})

    # 提取年份和月份
    df['year'] = df['bizTime'].dt.year
    df['month'] = df['bizTime'].dt.month
    df['year_month'] = df['bizTime'].dt.strftime('%Y-%m')

    return df


def analyze_expenses(df):
    """分析支出数据"""
    # 筛选支出数据
    expenses = df[df['type'] == '支出']

    if expenses.empty:
        return "没有支出数据可供分析"

    # 按类别统计支出
    category_expense = expenses.groupby('categoryName')['amount'].sum().reset_index()
    category_expense = category_expense.sort_values('amount', ascending=False)

    # 按年月统计支出
    time_expense = expenses.groupby('year_month')['amount'].sum().reset_index()
    time_expense = time_expense.sort_values('year_month')

    # 计算支出最多的类别
    max_category = category_expense.iloc[0] if not category_expense.empty else None

    # 计算每月平均支出
    monthly_avg = expenses.groupby(['year', 'month'])['amount'].sum().mean()

    # 计算支出总额
    total_expense = expenses['amount'].sum()

    return {
        'category_expense': category_expense,
        'time_expense': time_expense,
        'max_category': max_category,
        'monthly_avg': monthly_avg,
        'total_expense': total_expense
    }


def analyze_income(df):
    """分析收入数据"""
    # 筛选收入数据
    income = df[df['type'] == '收入']

    if income.empty:
        return "没有收入数据可供分析"

    # 按类别统计收入
    category_income = income.groupby('categoryName')['amount'].sum().reset_index()
    category_income = category_income.sort_values('amount', ascending=False)

    # 按年月统计收入
    time_income = income.groupby('year_month')['amount'].sum().reset_index()
    time_income = time_income.sort_values('year_month')

    # 计算收入最多的类别
    max_category = category_income.iloc[0] if not category_income.empty else None

    # 计算每月平均收入
    monthly_avg = income.groupby(['year', 'month'])['amount'].sum().mean()

    # 计算收入总额
    total_income = income['amount'].sum()

    return {
        'category_income': category_income,
        'time_income': time_income,
        'max_category': max_category,
        'monthly_avg': monthly_avg,
        'total_income': total_income
    }


def analyze_balance(df):
    """分析收支平衡"""
    # 按年月分组，计算每月收支
    monthly_data = df.groupby(['year', 'month', 'type'])['amount'].sum().unstack(fill_value=0)

    # 确保列顺序一致
    if '支出' not in monthly_data.columns:
        monthly_data['支出'] = 0
    if '收入' not in monthly_data.columns:
        monthly_data['收入'] = 0

    # 计算每月结余
    monthly_data['结余'] = monthly_data['收入'] - monthly_data['支出']

    # 转换索引为年月字符串
    monthly_data.index = [f"{y}-{m:02d}" for y, m in monthly_data.index]

    # 计算总收支和结余
    total_income = monthly_data['收入'].sum()
    total_expense = monthly_data['支出'].sum()
    total_balance = total_income - total_expense

    return {
        'monthly_data': monthly_data,
        'total_income': total_income,
        'total_expense': total_expense,
        'total_balance': total_balance
    }


def generate_visualizations(df, output_dir='output'):
    """生成可视化图表"""
    # 创建输出目录
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    # 分析数据
    expense_analysis = analyze_expenses(df)
    income_analysis = analyze_income(df)
    balance_analysis = analyze_balance(df)

    # 1. 支出类别饼图
    if isinstance(expense_analysis, dict):
        plt.figure(figsize=(10, 6))
        plt.pie(expense_analysis['category_expense']['amount'],
                labels=expense_analysis['category_expense']['categoryName'],
                autopct='%1.1f%%', startangle=90)
        plt.title('支出类别分布')
        plt.axis('equal')
        plt.tight_layout()
        plt.savefig(f'{output_dir}/expense_category_pie.png')
        plt.close()

    # 2. 收入类别饼图
    if isinstance(income_analysis, dict):
        plt.figure(figsize=(10, 6))
        plt.pie(income_analysis['category_income']['amount'],
                labels=income_analysis['category_income']['categoryName'],
                autopct='%1.1f%%', startangle=90)
        plt.title('收入类别分布')
        plt.axis('equal')
        plt.tight_layout()
        plt.savefig(f'{output_dir}/income_category_pie.png')
        plt.close()

    # 3. 支出趋势图
    if isinstance(expense_analysis, dict):
        plt.figure(figsize=(12, 6))
        sns.lineplot(x='year_month', y='amount', data=expense_analysis['time_expense'])
        plt.title('支出趋势')
        plt.xlabel('年月')
        plt.ylabel('金额(元)')
        plt.xticks(rotation=45)
        plt.tight_layout()
        plt.savefig(f'{output_dir}/expense_trend.png')
        plt.close()

    # 4. 收入趋势图
    if isinstance(income_analysis, dict):
        plt.figure(figsize=(12, 6))
        sns.lineplot(x='year_month', y='amount', data=income_analysis['time_income'])
        plt.title('收入趋势')
        plt.xlabel('年月')
        plt.ylabel('金额(元)')
        plt.xticks(rotation=45)
        plt.tight_layout()
        plt.savefig(f'{output_dir}/income_trend.png')
        plt.close()

    # 5. 收支对比图
    if isinstance(balance_analysis, dict):
        plt.figure(figsize=(12, 6))
        x = np.arange(len(balance_analysis['monthly_data'].index))
        width = 0.35

        plt.bar(x - width / 2, balance_analysis['monthly_data']['收入'], width, label='收入')
        plt.bar(x + width / 2, balance_analysis['monthly_data']['支出'], width, label='支出')

        plt.title('每月收支对比')
        plt.xlabel('年月')
        plt.ylabel('金额(元)')
        plt.xticks(x, balance_analysis['monthly_data'].index, rotation=45)
        plt.legend()
        plt.tight_layout()
        plt.savefig(f'{output_dir}/income_expense_comparison.png')
        plt.close()

    # 6. 结余趋势图
    if isinstance(balance_analysis, dict):
        plt.figure(figsize=(12, 6))
        plt.plot(balance_analysis['monthly_data'].index, balance_analysis['monthly_data']['结余'], marker='o')
        plt.title('每月结余趋势')
        plt.xlabel('年月')
        plt.ylabel('结余(元)')
        plt.xticks(rotation=45)
        plt.grid(True, linestyle='--', alpha=0.7)
        plt.tight_layout()
        plt.savefig(f'{output_dir}/balance_trend.png')
        plt.close()

    return output_dir


def generate_report(df, output_dir='output'):
    """生成分析报告"""
    # 创建输出目录
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    # 分析数据
    expense_analysis = analyze_expenses(df)
    income_analysis = analyze_income(df)
    balance_analysis = analyze_balance(df)

    # 生成报告
    with open(f'{output_dir}/financial_report.txt', 'w', encoding='utf-8') as f:
        f.write("财务分析报告\n")
        f.write("=" * 50 + "\n\n")

        # 基本信息
        start_date = df['bizTime'].min().strftime('%Y-%m-%d')
        end_date = df['bizTime'].max().strftime('%Y-%m-%d')
        f.write(f"数据期间: {start_date} 至 {end_date}\n")
        f.write(f"总记录数: {len(df)}\n")
        f.write("\n")

        # 支出分析
        f.write("支出分析\n")
        f.write("-" * 30 + "\n")
        if isinstance(expense_analysis, dict):
            f.write(f"总支出: {expense_analysis['total_expense']:.2f} 元\n")
            f.write(f"月均支出: {expense_analysis['monthly_avg']:.2f} 元\n\n")

            f.write("支出类别排行:\n")
            for _, row in expense_analysis['category_expense'].iterrows():
                f.write(
                    f"- {row['categoryName']}: {row['amount']:.2f} 元 ({row['amount'] / expense_analysis['total_expense'] * 100:.1f}%)\n")

            if expense_analysis['max_category'] is not None:
                f.write(
                    f"\n支出最多的类别: {expense_analysis['max_category']['categoryName']}, {expense_analysis['max_category']['amount']:.2f} 元\n")
        else:
            f.write(expense_analysis + "\n")
        f.write("\n")

        # 收入分析
        f.write("收入分析\n")
        f.write("-" * 30 + "\n")
        if isinstance(income_analysis, dict):
            f.write(f"总收入: {income_analysis['total_income']:.2f} 元\n")
            f.write(f"月均收入: {income_analysis['monthly_avg']:.2f} 元\n\n")

            f.write("收入类别排行:\n")
            for _, row in income_analysis['category_income'].iterrows():
                f.write(
                    f"- {row['categoryName']}: {row['amount']:.2f} 元 ({row['amount'] / income_analysis['total_income'] * 100:.1f}%)\n")

            if income_analysis['max_category'] is not None:
                f.write(
                    f"\n收入最多的类别: {income_analysis['max_category']['categoryName']}, {income_analysis['max_category']['amount']:.2f} 元\n")
        else:
            f.write(income_analysis + "\n")
        f.write("\n")

        # 收支平衡分析
        f.write("收支平衡分析\n")
        f.write("-" * 30 + "\n")
        if isinstance(balance_analysis, dict):
            f.write(f"总收入: {balance_analysis['total_income']:.2f} 元\n")
            f.write(f"总支出: {balance_analysis['total_expense']:.2f} 元\n")
            f.write(f"总结余: {balance_analysis['total_balance']:.2f} 元\n\n")

            f.write("每月收支详情:\n")
            for date, row in balance_analysis['monthly_data'].iterrows():
                f.write(f"- {date}: 收入 {row['收入']:.2f} 元, 支出 {row['支出']:.2f} 元, 结余 {row['结余']:.2f} 元\n")

            # 分析结余情况
            surplus_months = balance_analysis['monthly_data'][balance_analysis['monthly_data']['结余'] > 0]
            deficit_months = balance_analysis['monthly_data'][balance_analysis['monthly_data']['结余'] < 0]

            f.write(f"\n结余为正的月份数: {len(surplus_months)}\n")
            f.write(f"结余为负的月份数: {len(deficit_months)}\n")

            if not surplus_months.empty:
                max_surplus = surplus_months['结余'].max()
                max_surplus_month = surplus_months['结余'].idxmax()
                f.write(f"最大结余: {max_surplus:.2f} 元 (月份: {max_surplus_month})\n")

            if not deficit_months.empty:
                max_deficit = deficit_months['结余'].min()
                max_deficit_month = deficit_months['结余'].idxmin()
                f.write(f"最大赤字: {max_deficit:.2f} 元 (月份: {max_deficit_month})\n")
        else:
            f.write("无法进行收支平衡分析\n")
        f.write("\n")

        # 优化建议
        f.write("优化建议\n")
        f.write("-" * 30 + "\n")
        if isinstance(expense_analysis, dict) and not expense_analysis['category_expense'].empty:
            top_categories = expense_analysis['category_expense'].head(3)
            f.write("支出优化建议:\n")
            for _, row in top_categories.iterrows():
                if row['categoryName'] == '超市购物':
                    f.write(
                        f"- {row['categoryName']}占比较高 ({row['amount'] / expense_analysis['total_expense'] * 100:.1f}%), 建议制定购物清单，避免冲动消费\n")
                elif row['categoryName'] == '餐饮':
                    f.write(
                        f"- {row['categoryName']}占比较高 ({row['amount'] / expense_analysis['total_expense'] * 100:.1f}%), 建议减少外出就餐次数，自己做饭更健康经济\n")
                elif row['categoryName'] == '交通':
                    f.write(
                        f"- {row['categoryName']}占比较高 ({row['amount'] / expense_analysis['total_expense'] * 100:.1f}%), 建议优化通勤路线，考虑公共交通或拼车\n")
                else:
                    f.write(
                        f"- {row['categoryName']}占比较高 ({row['amount'] / expense_analysis['total_expense'] * 100:.1f}%), 建议评估是否有优化空间\n")

        if isinstance(balance_analysis, dict):
            if balance_analysis['total_balance'] < 0:
                f.write("\n财务状况: 总体处于赤字状态，建议增加收入或减少支出\n")
            else:
                f.write("\n财务状况: 总体处于盈余状态，建议合理规划储蓄和投资\n")
        f.write("\n")

        f.write("=" * 50 + "\n")
        f.write(f"报告生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")


def main():
    # 提示用户输入JSON文件路径
    file_path = 'wacai_output.json'

    try:
        # 加载数据
        df = load_data(file_path)

        # 生成可视化图表
        output_dir = generate_visualizations(df)
        print(f"可视化图表已保存到 {output_dir} 目录")

        # 生成分析报告
        generate_report(df, output_dir)
        print(f"分析报告已保存到 {output_dir}/financial_report.txt")

        # 显示基本统计信息
        print("\n基本统计信息:")
        print(f"数据期间: {df['bizTime'].min().strftime('%Y-%m-%d')} 至 {df['bizTime'].max().strftime('%Y-%m-%d')}")
        print(f"总记录数: {len(df)}")
        print(f"总支出: {df[df['type'] == '支出']['amount'].sum():.2f} 元")
        print(f"总收入: {df[df['type'] == '收入']['amount'].sum():.2f} 元")

    except FileNotFoundError:
        print(f"错误: 文件 '{file_path}' 不存在")
    except json.JSONDecodeError:
        print(f"错误: 文件 '{file_path}' 不是有效的JSON格式")
    except Exception as e:
        print(f"发生错误: {e}")


if __name__ == "__main__":
    main()
